package com.finger.wx.assistant.dao;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import android.util.Log;

import com.finger.wx.assistant.dict.KeyDict;
import com.finger.wx.assistant.util.ToolAdb;
import com.finger.wx.assistant.util.ToolFile;
import com.finger.wx.assistant.util.ToolString;
import com.finger.wx.assistant.util.xml.Node;
import com.finger.wx.assistant.util.xml.NodeBuilder;
import com.finger.wx.assistant.util.xml.SimpleXmlFilter;
import com.finger.wx.assistant.util.xml.SimpleXmlParser;
import com.finger.wx.assistant.util.xml.UiXml;
import com.finger.wx.assistant.util.xml.XmlFilter;
import com.finger.wx.assistant.util.xml.XmlParser;
import com.finger.wx.assistant.vo.Constant;
import com.finger.wx.assistant.vo.Point;

//http://blog.csdn.net/eofguo/article/details/52981720
public class CmdDaoImpl implements CmdDao {

	protected static final String TAG = "CmdDaoImpl";

	@Override
	public void tap(int x, int y) {
		String cmd = String.format("input tap %d  %d", x, y);
		boolean ret = ToolAdb.execShell(cmd);
		Log.i(TAG, "cmd:" + cmd + ",ret:" + ret);
	}

	@Override
	public void touch(int x, int y, int time) {
		String cmd = String.format("input touch  %d  %d  %d", x, y, time);
		boolean ret = ToolAdb.execShell(cmd);
		Log.i(TAG, "cmd:" + cmd + ",ret:" + ret);
	}

	@Override
	public void swipe(int x1, int y1, int x2, int y2, int time) {
		String cmd = String.format("input swipe  %d  %d  %d  %d  %d", x1, y1, x2, y2, time);
		boolean ret = ToolAdb.execShell(cmd);
		Log.i(TAG, "cmd:" + cmd + ",ret:" + ret);
	}

	@Override
	public void swipe(int x1, int y1, int x2, int y2) {
		ToolAdb.execShell(String.format("input swipe  %d  %d  %d  %d  %d", x1, y1, x2, y2, 200));
	}

	@Override
	public void keyPress(String key) {
		int code = KeyDict.getInstance().getCode(key);
		ToolAdb.execShell(String.format("input keyevent  %s", code));
	}

	@Override
	public void inputTxt(String txt) {
		// ToolAdb.execShell(String.format("input text  %s", txt));
		ToolAdb.execShell(String.format("am broadcast -a ADB_INPUT_TEXT --es msg  '%s'", txt));
	}

	@Override
	public String tempPath() {
		return Constant.tempFilePath;
	}

	@Override
	public String tempFile(String filename) {
		String tPath = tempPath();
		String filePath = "";
		if (filename == null) {
			filePath = tPath + "shs_temp.txt";

		} else {
			filePath = tPath + filename;
		}

		File file = new File(filePath);
		if (!file.getParentFile().exists()) {
			file.getParentFile().mkdirs();
		}

		return filePath;
	}

	@Override
	public void findFileDelete(String filepath, String filename) {
		ToolAdb.execShell(String.format("find %s -name '%s' | xargs rm -rf", filepath, filename));
	}

	@Override
	public void delFile(String filename) {
		ToolAdb.execShell(String.format("rm  %s", filename));
	}

	@Override
	public void createFolder(String folderpath) {
		ToolAdb.execShell(String.format("mkdir %s", folderpath));
	}

	@Override
	public void writeFileLine(String path, int line, String str) {
		try {
			ToolFile.appendToFileLine(str, new File(path), line);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@Override
	public String readFile(String filepath, boolean isdel) {
		String ret = "";
		try {
			ret = ToolFile.readFileByLines(filepath);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (isdel) {
				delFile(filepath);
			}
		}
		return ret;
	}

	@Override
	public void chomd(String path, int per) {
		if (per == 0) {
			chomdEx(path, 666);
		} else if (per == 1) {
			chomdEx(path, 444);
		} else if (per == 2) {
			chomdEx(path, 777);
		}
	}

	@Override
	public void chomdEx(String path, int per) {
		ToolAdb.execShell(String.format("chmod  %d  %s", per, path));
	}

	@Override
	public String scanPath(String path, String filter) {
		// TODO
		return null;
	}

	@Override
	public String getTempFile(String path, String prefix, String postfix, int length) {
		StringBuilder sb = new StringBuilder();
		sb.append(path);
		sb.append(prefix);
		for (int i = 0; i < length; i++) {
			sb.append(new Random().nextInt(length));
		}
		sb.append(postfix);
		return sb.toString();
	}

	@Override
	public String getFileName(String path) {
		String ret = "";
		Pattern p = Pattern.compile("/([^/]+)");
		// 空格结束
		Matcher m = p.matcher(path);
		while (m.find()) {
			ret = m.group(1);
		}
		return ret;
	}

	@Override
	public String getFileType(String path) {
		String filename = getFileName(path);
		int index = filename.lastIndexOf(".");
		return filename.substring(index + 1);
	}

	@Override
	public void runApp(String packagename) {
		String runapp_cmd = String.format("am start -a  %s", packagename);
		ToolAdb.execShell(runapp_cmd);
	}

	@Override
	public void runApp(String packagename, String activityname) {
		String runapp_cmd = String.format("am start -n %s/%s", packagename, activityname);
		ToolAdb.execShell(runapp_cmd);
	}

	@Override
	public void killApp(String packagename) {
		// 先判断该应用是否在运行
		String ret = execute(String.format("ps |grep  %s", packagename), null);
		if (ToolString.isNoBlankAndNoNull(ret)) {
			String killapp_cmd = String.format("am force-stop  %s", packagename);
			ToolAdb.execShell(killapp_cmd);
		}
	}

	@Override
	public void openWeb(String url) {
		if (!url.startsWith("http://")) {
			url = "http://" + url;
		}
		ToolAdb.execShell(String.format("am start -a android.intent.action.VIEW -d  %s", url));
	}

	@Override
	public void weixinUrl(String packagename, String url) {
		if (!url.startsWith("http://")) {
			url = "http://" + url;
		}
		ToolAdb.execShell(String.format("am start -n %s/.plugin.webview.ui.tools.WebViewUI -d '%s'", packagename, url));
	}

	@Override
	public void appClean(String packagename) {
		ToolAdb.execShell(String.format("pm clear %s", packagename));
	}

	@Override
	public List<String> getAppList(int type) {
		String sRet = "";
		List<String> result = new ArrayList<String>();
		if (type == 0) {
			sRet = execute("pm list packages -3", null);
		} else if (type == 1) {
			sRet = execute("pm list packages -s", null);
		} else if (type == 2) {
			sRet = execute("pm list packages", null);
		}

		if (ToolString.isNoBlankAndNoNull(sRet)) {
			Pattern p = Pattern.compile("package:([^\r\n]+)");
			Matcher m = p.matcher(sRet);
			while (m.find()) {
				result.add(m.group(1));
			}
		}
		return result;
	}

	@Override
	public List<String> getRunningAppList() {
		List<String> result = new ArrayList<String>();
		String ret = execute("ps", null);
		if (ToolString.isNoBlankAndNoNull(ret)) {
			for (String str : ret.split("[\r\n]")) {
				result.add(str.split("\\s+")[8]);
			}
		}
		return result;
	}

	@Override
	public String appLastUpdateTime(String packagename) {
		String result = "";
		String updateTime = execute(String.format("dumpsys package %s |grep lastUpdateTime", packagename), null);
		if (ToolString.isNoBlankAndNoNull(updateTime)) {
			result = updateTime.replace("\\n", "").split("=")[1];
		}
		return result;
	}

	@Override
	public String appVersion(String packagename) {
		String result = "";
		String appVersion = execute(String.format("dumpsys package %s |grep versionName ", packagename), null);
		if (ToolString.isNoBlankAndNoNull(appVersion)) {
			result = appVersion.replace("\\n", "").split("=")[1];
		}
		return result;
	}

	@Override
	public String appFirstInstallTime(String packagename) {
		String result = "";
		String insTime = execute(String.format("dumpsys package %s |grep firstInstallTime ", packagename), null);
		if (ToolString.isNoBlankAndNoNull(insTime)) {
			result = insTime.replace("\\n", "").split("=")[1];
		}
		return result;
	}

	@Override
	public void disableApp(String packagename) {
		ToolAdb.execShell(String.format("pm disable %s ", packagename));
	}

	@Override
	public void enableApp(String packagename) {
		ToolAdb.execShell(String.format("pm enable %s", packagename));
	}

	@Override
	public boolean existApp(String packagename) {
		String ret = execute("pm list packages", null);
		if (ret.contains(packagename)) {
			return true;
		}
		return false;
	}

	@Override
	public List<String> getNotification(String packagename) {
		String info = execute("dumpsys notification", null);
		// 没有消息
		if (!ToolString.isNoBlankAndNoNull(info)) {
			return null;
		}

		// 按顺序存储包名
		List<String> plist = new ArrayList<String>();
		// 解析出包名
		Pattern p1 = Pattern.compile("pkg=[^ ]+");
		Matcher m1 = p1.matcher(info);
		while (m1.find()) {
			String pk = m1.group(0).substring(4);
			plist.add(pk);
		}

		// 判断是否有该包名的消息
		if (!plist.contains(packagename)) {
			return null;
		}

		// 包名为key,消息为value
		Map<String, List<String>> map = new HashMap<String, List<String>>();
		// 按包名分隔
		String[] strs = info.split("pkg=[^ ]+");
		for (int i = 1; i < strs.length; i++) {
			List<String> msg = null;
			String key = plist.get(i - 1);
			if (map.containsKey(key)) {
				msg = map.get(key);
			} else {
				msg = new ArrayList<String>();
			}
			String value = "";
			Pattern p2 = Pattern.compile("tickerText=[^\r\n]+");
			// 空格结束
			Matcher m2 = p2.matcher(strs[i]);
			while (m2.find()) {
				value = m2.group(0).substring(11);
			}

			if (!value.equals("") && !value.equals("null")) {
				msg.add(value);
				map.put(key, msg);
			}
		}

		if (map.containsKey(packagename)) {
			return map.get(packagename);
		}

		return null;
	}

	@Override
	public void install(String path) {
		String install_cmd = String.format("pm install -r  %s", path);
		ToolAdb.execShell(install_cmd);
	}

	@Override
	public void uninstall(String packagename) {
		String uninstall_cmd = String.format("pm uninstall   %s", packagename);
		ToolAdb.execShell(uninstall_cmd);
	}

	@Override
	public void runUrl(String url, int id) {
		String tmpact = "";
		switch (id) {
		case 0:// 360浏览器
			tmpact = "com.qihoo.browser/com.qihoo.browser.BrowserActivity";
			break;
		case 1:// QQ浏览器
			tmpact = "com.tencent.mtt.x86/com.tencent.mtt.x86.MainActivity";
			break;
		case 2:// 海豚浏览器
			tmpact = "com.dolphin.browser.xf/mobi.mgeek.TunnyBrowser.MainActivity";
			break;
		case 3:// 欧朋浏览器
			tmpact = "com.oupeng.browser/com.opera.android.OperaMainActivity";
			break;
		case 4:// 遨游浏览器
			tmpact = "com.mx.browser/com.mx.browser.MxBrowserActivity";
			break;
		case 5:// UC浏览器
			tmpact = "com.UCMobile/com.uc.browser.InnerUCMobile";
			break;
		default:
			tmpact = "com.android.browser/com.android.browser.BrowserActivity";
			break;
		}
		String browse_cmd = String.format("am start -n  %s -d  %s", tmpact, url);
		ToolAdb.execShell(browse_cmd);
	}

	@Override
	public String getTopActivity(int type) {
		String result = "";
		String ret = execute("dumpsys activity top ", null);
		Pattern p = null;
		if (type == 1) {
			p = Pattern.compile("ACTIVITY ([^/]+)");
		} else if (type == 2) {
			p = Pattern.compile("ACTIVITY ([^ ]+)");
		}

		Matcher m = p.matcher(ret);
		while (m.find()) {
			result = m.group(1);
		}
		return result;
	}

	@Override
	public String getUIXml() {
		String filename = tempFile(System.currentTimeMillis() + ".xml");
		String ui_cmd = String.format("uiautomator dump  %s", filename);
		ToolAdb.execShell(ui_cmd);
		chomd(filename, 2);
		return readFile(filename, true);
	}

	@Override
	public List<UiXml> getUIXmlEx() {
		String filename = tempFile(System.currentTimeMillis() + ".xml");
		String cmd = String.format("uiautomator dump  %s", filename);
		boolean ret = ToolAdb.execShell(cmd);

		int times = 1;
		while ((ret == false || !new File(filename).exists()) && times < 3) {
			sleep(1000);
			ret = ToolAdb.execShell(cmd);
			times++;
		}

		chomd(filename, 2);
		Log.i(TAG, "cmd:" + cmd + ",ret:" + ret);
		return parseTextFromXml(filename, true);
	}
	
	
	@Override
	public List<UiXml> getUIXmlEx2() {
		String filename = tempFile(System.currentTimeMillis() + ".xml");
		String cmd = String.format("uiautomator dump  %s", filename);
		boolean ret = ToolAdb.execShell(cmd);

		int times = 1;
		while ((ret == false || !new File(filename).exists()) && times < 3) {
			sleep(1000);
			ret = ToolAdb.execShell(cmd);
			times++;
		}

		chomd(filename, 2);
		Log.i(TAG, "cmd:" + cmd + ",ret:" + ret);
		return parseIdFromXml(filename, true);
	}

	@Override
	public boolean topUIContains(String s) {
		String filename = tempFile(System.currentTimeMillis() + ".xml");
		String cmd1 = String.format("uiautomator dump  %s", filename);
		ToolAdb.execShell(cmd1);

		String cmd2 = String.format("cat %s |grep  %s", filename, s);
		String ret = execute(cmd2, null);

		delFile(filename);
		if (ToolString.isNoBlankAndNoNull(ret)) {
			return true;
		}

		return false;
	}

	@Override
	public Point findCompontById(String id){
		Point point = null;
		for (UiXml u : getUIXmlEx2()) {
			if (id.equals(u.getId())) {
				point = new Point(u.getX(), u.getY());
			}
		}
		return point;
	}
	
	@Override
	public Point findCompontLocation(String textVal, String nclassVal) {
		Point point = null;
		for (UiXml u : getUIXmlEx()) {
			if (textVal.equals(u.getText()) && nclassVal.equals(u.getNclass())) {
				point = new Point(u.getX(), u.getY());
				break;
			}
		}
		return point;
	}

	@Override
	public void findCompontsLocation(List<Point> points) {
		for (UiXml u : getUIXmlEx()) {
			for (Point p : points) {
				if ((p.getTextVal()).equals(u.getText()) && (p.getNclassVal()).equals(u.getNclass())) {
					p.setX(u.getX());
					p.setY(u.getY());
				}
			}
		}
	}

	@Override
	public String getScreen(int f) {
		String ret = execute("dumpsys window", null);
		Pattern p = Pattern.compile("init=(\\d+)x(\\d+) (\\d+)dpi");
		Matcher m = p.matcher(ret);
		String result = "";
		while (m.find()) {
			result = m.group(f);
		}
		return result;
	}

	@Override
	public void setTime(String day, String time) {
		String time_cmd = String.format("date -s  %s  %s", day, time);
		ToolAdb.execShell(time_cmd);
	}

	@Override
	public void openAirplane() {
		String[] open_cmd = { "settings put global airplane_mode_on 1",
				"am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true" };
		ToolAdb.execShell(open_cmd);
	}

	@Override
	public void closeAirplane() {
		String[] close_cmd = { "settings put global airplane_mode_on 0",
				"am broadcast -a android.intent.action.AIRPLANE_MODE --ez state false" };
		ToolAdb.execShell(close_cmd);
	}

	@Override
	public boolean isScreenOn() {
		String ret = execute("dumpsys power", null);
		Pattern p = Pattern.compile("mScreenOn=true");
		Matcher m = p.matcher(ret);
		while (m.find()) {
			return true;
		}
		return false;
	}

	@Override
	public boolean isBluetooh() {
		String ret = execute("getprop bluetooth.status", null);
		if (ret.equals("on")) {
			return true;
		}
		return false;
	}

	@Override
	public boolean isVm() {
		String retinfo = execute("cat /proc/cpuinfo", null);
		if (ToolString.isNoBlankAndNoNull(retinfo)) {
			if (retinfo.contains("model name") && retinfo.contains("vendor_id")) {
				return true;
			}
		}
		return false;
	}

	@Override
	public void reboot() {
		ToolAdb.execShell("reboot");
	}

	@Override
	public void shutdown() {
		ToolAdb.execShell("reboot -p");
	}

	@Override
	public String getAndroidVer() {
		return execute("getprop ro.build.version.release", null);
	}

	@Override
	public boolean isConnectWifi() {
		String ret = execute("dumpsys wifi", null);
		Pattern p = Pattern.compile("enabled");
		Matcher m = p.matcher(ret);
		while (m.find()) {
			return true;
		}
		return false;
	}

	@Override
	public void controlData(int flag) {
		if (flag == 0) {
			ToolAdb.execShell("svc data enable");
		} else {
			ToolAdb.execShell("svc data disable");
		}
	}

	@Override
	public void controlWifi(int flag) {
		if (flag == 0) {
			ToolAdb.execShell("svc wifi enable");
		} else {
			ToolAdb.execShell("svc wifi disable");
		}
	}

	@Override
	public String getIp() {
		// TODO
		return null;
	}

	@Override
	public String getMac() {
		String mac = "00:00:00:00:00:00";
		boolean isExist = ToolFile.isExsit("/sys/class/net/wlan0/address");
		if (isExist) {
			mac = execute("cat /sys/class/net/wlan0/address", null);
		} else {
			String info = execute("getprop", null);
			mac = info;
		}
		return mac;
	}

	@Override
	public String execute(String cmd, String filename) {
		String tf = tempFile(filename);
		cmd = cmd + " > " + tf;
		ToolAdb.execShell(cmd);
		int times = 1;
		while (!new File(tf).exists() && times < 3) {
			sleep(1000);
			ToolAdb.execShell(cmd);
			times++;
		}
		// 文件授权
		chomd(tf, 2);
		return readFile(tf, true);
	}

	@Override
	public void sleep(int ms) {
		try {
			Thread.sleep(ms);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 获取所有文本不为空的节点
	 * 
	 * @param filepath
	 * @param isdel
	 * @return
	 */
	private List<UiXml> parseTextFromXml(String filepath, boolean isdel) {
		List<UiXml> list = new ArrayList<UiXml>();
		File f = new File(filepath);
		XmlFilter filter = null;
		try {
			filter = new SimpleXmlFilter(f);
			XmlParser parser = new SimpleXmlParser();
			NodeBuilder builder = new NodeBuilder(parser, filter);
			Node node = builder.getRoot();
			parseTextNode(node, list);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			// 删除文件
			if (isdel) {
				delFile(filepath);
			}
		}

		return list;
	}

	/**
	 * 解析出文本不为空的节点
	 * 
	 * @param node
	 * @param list
	 */
	private void parseTextNode(Node node, List<UiXml> list) {
		Map<String, String> attribute = node.getAttribute();
		if (ToolString.isNoBlankAndNoNull(attribute.get("text"))
				|| ToolString.isNoBlankAndNoNull(attribute.get("content-desc"))) {
			UiXml uXml = new UiXml();
			uXml.setId(attribute.get("resource_id"));
			uXml.setNclass(attribute.get("class"));
			String text = ToolString.isNoBlankAndNoNull(attribute.get("text")) ? attribute.get("text") : attribute
					.get("content-desc");
			uXml.setText(text);
			uXml.setBounds(attribute.get("bounds"));
			list.add(uXml);
		}
		if (node.isHaveChildren()) {
			List<Node> childs = node.getChildNode();
			for (Node ch : childs) {
				parseTextNode(ch, list);
			}
		}
	}

	/**
	 * 获取所有ID不为空的节点
	 * 
	 * @param filepath
	 * @param isdel
	 * @return
	 */
	private List<UiXml> parseIdFromXml(String filepath, boolean isdel) {
		List<UiXml> list = new ArrayList<UiXml>();
		File f = new File(filepath);
		XmlFilter filter = null;
		try {
			filter = new SimpleXmlFilter(f);
			XmlParser parser = new SimpleXmlParser();
			NodeBuilder builder = new NodeBuilder(parser, filter);
			Node node = builder.getRoot();
			parseIdNode(node, list);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			// 删除文件
			if (isdel) {
				delFile(filepath);
			}
		}

		return list;
	}

	/**
	 * 解析出id不为空的节点
	 * 
	 * @param node
	 * @param list
	 */
	private void parseIdNode(Node node, List<UiXml> list) {
		Map<String, String> attribute = node.getAttribute();
		if (ToolString.isNoBlankAndNoNull(attribute.get("resource_id"))) {
			UiXml uXml = new UiXml();
			uXml.setId(attribute.get("resource_id"));
			uXml.setNclass(attribute.get("class"));
			String text = ToolString.isNoBlankAndNoNull(attribute.get("text")) ? attribute.get("text") : attribute
					.get("content-desc");
			uXml.setText(text);
			uXml.setBounds(attribute.get("bounds"));
			list.add(uXml);
		}
		if (node.isHaveChildren()) {
			List<Node> childs = node.getChildNode();
			for (Node ch : childs) {
				parseIdNode(ch, list);
			}
		}
	}

}
